package com.fjec.user.service.impl;

import com.fjec.common.Const;
import com.fjec.common.enums.EnumLoginType;
import com.fjec.common.enums.EnumSysCode;
import com.fjec.common.exception.LoginException;
import com.fjec.common.okhttp.OkHttp;
import com.fjec.common.protocol.JsonResult;
import com.fjec.common.shiro.AccountInfo;
import com.fjec.common.shiro.MyUserToken;
import com.fjec.common.util.DateUtil;
import com.fjec.common.util.JsonUtil;
import com.fjec.user.entity.SysUser;
import com.fjec.user.entity.SysUserApp;
import com.fjec.user.entity.WechatResponse;
import com.fjec.user.feign.BaseClient;
import com.fjec.user.feign.MarketClient;
import com.fjec.user.service.ILoginService;
import com.fjec.user.service.ISysUserAppService;
import com.fjec.user.service.ISysUserService;
import com.fjec.user.view.LoginVO;
import com.fjec.user.wechat.WeChatConst;
import com.google.common.base.Strings;
import com.vdurmont.emoji.EmojiParser;
import org.apache.commons.collections.MapUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Map;
import java.util.concurrent.locks.Lock;

@Service
@Transactional
public class LoginServiceImpl implements ILoginService {

    @Autowired
    private OkHttp okHttp;

    @Resource
    private BaseClient baseClient;

    @Resource
    private MarketClient marketClient;

    @Autowired
    private ISysUserAppService sysUserAppService;

    @Autowired
    private ISysUserService sysUserService;

    @Resource
    private RedisLockRegistry redisLockRegistry;

    @Override
    public JsonResult wxSmallAppLogin(String jsCode, Long coopId, String nickName, String headPic) throws Exception {
        String url = WeChatConst.getUrl(jsCode);
        String body = okHttp.get(url);
        WechatResponse wechatResponse = JsonUtil.jsonToObject(body, WechatResponse.class);
        // 校验参数是否正常转换
        if (wechatResponse.getErrcode() != 0) {
            return JsonResult.failure()
                    .code(EnumSysCode.ERR_0031.getCode())
                    .message(EnumSysCode.ERR_0031.getMsg())
                    .build();
        }
        String openId = wechatResponse.getOpenid();
        Lock lock = redisLockRegistry.obtain(Const.REG_OPENID_LOCK_KEY + openId);
        try {
            lock.lock();
            SysUser user = sysUserService.getSysUserByUserAppId(openId, Const.APP_TYPE_WX_SMALL_APP);
            if (user != null) {
                // 用户已创建，如果传入的昵称和头像不为空，则更新
                if (!Strings.isNullOrEmpty(nickName) && !Strings.isNullOrEmpty(headPic)) {
                    this.updateNickNameAndHeadPic(user.getId(), EmojiParser.removeAllEmojis(nickName), headPic);
                }
            } else {
                // 创建用户
                this.createUser(openId, coopId, EmojiParser.removeAllEmojis(nickName), headPic);
            }
            AuthenticationToken token = new MyUserToken(openId, "", EnumLoginType.WECHAT_APP, null);
            SecurityUtils.getSubject().login(token);
            // 返回登录view
            LoginVO loginVO = new LoginVO();
            loginVO.setUserId(AccountInfo.getUserId().toString());
            loginVO.setSessionKey(AccountInfo.getSession().getId().toString());
            loginVO.setRoles(AccountInfo.getRole());
            Integer busiType = AccountInfo.getBusiType();
            loginVO.setBusiType(busiType);
            if (busiType == 1) {
                loginVO.setNickName(AccountInfo.getWxNickName());
            } else {
                loginVO.setNickName(AccountInfo.getShopName());
            }
            loginVO.setShopName(AccountInfo.getShopName());
            loginVO.setHeadPic(AccountInfo.getHeadPic());
            return JsonResult.success()
                    .data(loginVO)
                    .build();
        } catch (Exception e) {
            throw e;
        } finally {
            lock.unlock();
        }
    }

    @Override
    public JsonResult wxSmallAppReg(String jsCode, Long coopId) throws Exception {
        String url = WeChatConst.getUrl(jsCode);
        String body = okHttp.get(url);
        WechatResponse wechatResponse = JsonUtil.jsonToObject(body, WechatResponse.class);
        // 校验参数是否正常转换
        if (wechatResponse.getErrcode() != 0) {
            return JsonResult.failure()
                    .code(EnumSysCode.ERR_0031.getCode())
                    .message(EnumSysCode.ERR_0031.getMsg())
                    .build();
        }
        String openId = wechatResponse.getOpenid();
        Lock lock = redisLockRegistry.obtain(Const.REG_OPENID_LOCK_KEY + openId);
        try {
            lock.lock();
            SysUser user = sysUserService.getSysUserByUserAppId(openId, Const.APP_TYPE_WX_SMALL_APP);
            if (user == null) {
                this.createUser(openId, coopId, null, null);
            }
            return JsonResult.success()
                    .build();
        } catch (Exception e) {
            throw e;
        } finally {
            lock.unlock();
        }
    }

    /**
     * 创建用户
     *
     * @param openId   不可为空
     * @param coopId   可为空
     * @param nickName 可为空
     * @param headPic  可为空
     */
    private void createUser(String openId, Long coopId, String nickName, String headPic) throws Exception {
        // 用户不存在创建新用户
        SysUser user = new SysUser();
        user.setLocked(0);
        user.setCreateTime(DateUtil.nowLdt());
        boolean saved = sysUserService.save(user);
        if (!saved) {
            throw new LoginException(EnumSysCode.ERR_3006);
        }
        // 创建用户和应用之间的关系
        SysUserApp sysUserApp = new SysUserApp();
        sysUserApp.setUserId(user.getId());
        sysUserApp.setAppType(Const.APP_TYPE_WX_SMALL_APP);
        sysUserApp.setUserAppId(openId);
        saved = sysUserAppService.save(sysUserApp);
        if (!saved) {
            throw new LoginException(EnumSysCode.ERR_3006);
        }
        // 创建个人信息
        if (!Strings.isNullOrEmpty(nickName) && !Strings.isNullOrEmpty(headPic)) {
            // 下载并传微信头像
            String headPicUrl = this.handleHeadPic(user.getId(), nickName, headPic);
            saved = marketClient.savePersonal(user.getId(), coopId, nickName, headPicUrl);
        } else {
            saved = marketClient.savePersonal(user.getId(), coopId, null, null);
        }
        if (!saved) {
            throw new LoginException(EnumSysCode.ERR_3001);
        }
    }

    /**
     * 更新用户昵称和头像
     *
     * @param userId
     * @param nickName
     * @param headPic
     * @throws Exception
     */
    private void updateNickNameAndHeadPic(Long userId, String nickName, String headPic) throws Exception {
        // 下载并传微信头像
        String headPicUrl = this.handleHeadPic(userId, nickName, headPic);
        // 更新个人信息
//        boolean saved =
        marketClient.updatePersonal(userId, nickName, headPicUrl);
//        if (!saved) {
//            throw new LoginException(EnumSysCode.ERR_3001);
//        }
    }

    private String handleHeadPic(Long userId, String nickName, String headPic) throws Exception {
        String file = okHttp.convertUrl2Base64(headPic);
        Map<String, Object> baseMap = baseClient.base64Upload(file, "user_head_pic.png", 1, userId, 0);
        String headPicUrl = MapUtils.getString(baseMap, "url");
//        if (Strings.isNullOrEmpty(headPicUrl)) {
//            throw new LoginException(EnumSysCode.ERR_3001);
//        }
        return headPicUrl;
    }

}
